/*
 * Copyright (C) 2014 Wei Chou (weichou2010@gmail.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.wei.c.widget;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.AnimationDrawable;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AnimationUtils;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.Scroller;

import com.wei.c.lib.R;

public abstract class AbsPull2RefreshListView extends ListView implements OnScrollListener {

	/**当前为正在下拉状态**/
	public final static int STATE_PULL_TO_REFRESH			= 0;
	/**当前为下拉到足够的位置（通常为headerView的高度），表示可以在松开时触发{@link #postOnRefresh()}**/
	public final static int STATE_RELEASE_REFRESH			= 1;
	/**当前为正在刷新数据状态（headerView拉出来，而且触摸状态为已松开）**/
	public final static int STATE_REFRESHING				= 2;
	/**当前为正在加载更多数据（footerView出现了）**/
	public final static int STATE_LOADING					= 3;
	/**当前为正在下拉状态**/
	public final static int STATE_DONE						= 4;

	/**拖动的粘滞系数**/
	private final static int RATIO3 = 3, RATIO2 = 2;

	private ViewGroup mHeaderView, mFooterView;
	private int mHeaderPullEnoughAlignViewId;
	private int mHeaderHidePaddingTop = 0;
	private int mHeaderPullEnoughPaddingTop = 0;
	private int mHeaderMinShowTime = 2000;
	private int mHeaderHideAnimDuration = 300;

	private int mHeaderHeight;
	private float mStartY, mPrevMotionY;
	private int mCurrentPaddingTop;
	private int mFirstItemIndex;
	private long mRefreshingTimeStart;

	/**header和footer共用同一个state的，以免同时执行两次加载**/
	private int mState = STATE_DONE;
	private int mScrollState = OnScrollListener.SCROLL_STATE_IDLE;

	private int mPointerId = -1;
	private boolean mRecored = false;
	private boolean mLoading = false;
	private boolean mRefreshable = false;
	private boolean mFooterShown = false;
	private boolean mEventBlocked = false;
	private boolean mWaitingForDone = false;
	private boolean mTouched = false;
	private boolean mFingerUpped = false;
	private boolean mFooterHasMore = true;
	private boolean mFooterHasMorePrev = false;
	private boolean mAttachedToWindow = false;
	private boolean mSuspendPerformRefreshing = false;
	private boolean mSuspendSetRefreshComplete = false;
	private boolean mSuspendSetLoadComplete = false;
	private boolean mSuspendHasMore = false;

	private OnRefreshListener mRefreshListener;
	private Scroller mScroller;

	public AbsPull2RefreshListView(Context context) {
		super(context);
		setInterpolator(null);
		init(context);
	}

	public AbsPull2RefreshListView(Context context, AttributeSet attrs) {
		this(context, attrs, android.R.attr.listViewStyle);
	}

	public AbsPull2RefreshListView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);

		TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Pull2RefreshListView, defStyle, 0);
		mHeaderMinShowTime = a.getInt(R.styleable.Pull2RefreshListView_headerMinShowTime, mHeaderMinShowTime);
		mHeaderHideAnimDuration = a.getInt(R.styleable.Pull2RefreshListView_headerHideAnimDuration, mHeaderHideAnimDuration);
		mHeaderPullEnoughAlignViewId = a.getResourceId(R.styleable.Pull2RefreshListView_headerPullEnoughAlignView, 0);
		setInterpolator(a.getResourceId(R.styleable.Pull2RefreshListView_headerHideInterpolator, 0));
		a.recycle();

		init(context);
	}

	public void setInterpolator(int interpolatorId) {
		Interpolator interpolator = null;
		if (interpolatorId > 0) try {
			interpolator = AnimationUtils.loadInterpolator(getContext(), interpolatorId);
		}catch(Exception e) {
			e.printStackTrace();
		}
		setInterpolator(interpolator);
	}

	public void setInterpolator(Interpolator interpolator) {
		if (interpolator == null) interpolator = new DecelerateInterpolator();
		mScroller = new Scroller(getContext(), interpolator);
	}

	private void init(Context context) {
		setCacheColorHint(0);
		LayoutInflater inflater = LayoutInflater.from(context);

		/*RelativeLayout当设置paddingTop小于0时，会直接全部隐藏，而不是隐藏部分。
		mHeaderView = new RelativeLayout(getContext());
		mHeaderView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
		RelativeLayout.LayoutParams lpHeader = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
		lpHeader.addRule(RelativeLayout.CENTER_HORIZONTAL);
		mHeaderView.addView(getLoadingViewHeader(inflater), lpHeader);*/

		mHeaderView = new LinearLayout(getContext());
		mHeaderView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
		LinearLayout.LayoutParams lpHeader = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
		lpHeader.gravity = Gravity.CENTER_HORIZONTAL;
		mHeaderView.addView(getLoadingViewHeader(inflater), lpHeader);

		mFooterView = new RelativeLayout(getContext());
		mFooterView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
		LinearLayout.LayoutParams lpFooter = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
		lpFooter.gravity = Gravity.CENTER_HORIZONTAL;
		mFooterView.addView(getLoadingViewFooter(inflater), lpFooter);

		addHeaderView(mHeaderView, null, false);
		addFooterView(mFooterView, null, false);

		setHeaderDividersEnabled(false);
		setFooterDividersEnabled(true);

		setOnScrollListener(this);
		setOnFooterClick();
	}

	public int getState() {
		return mState;
	}

	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		super.onLayout(changed, l, t, r, b);
		if (mHeaderHeight == 0) {
			mHeaderHeight = mHeaderView.getHeight();
			mHeaderHidePaddingTop = -mHeaderHeight;
			if (mHeaderPullEnoughAlignViewId > 0) {
				View view = mHeaderView.findViewById(mHeaderPullEnoughAlignViewId);
				if (view != null) mHeaderPullEnoughPaddingTop = -view.getTop();
			}
			/* 在onLayout()里执行mHeaderView.setPadding()之后，requestLayout()可能被忽略，而
			 * 随后的再次执行mHeaderView.setPadding()将不起作用，因为没有改变。因此要post到下个消息循环来执行。
			 */
			post(new Runnable() {	//由于setPadding()会requestLayout()，如果将本方法放在外面将导致死循环
				@Override
				public void run() {
					if (mState == STATE_DONE) hideHeaderDirectly();
				}
			});
		}
	}

	/**在内容变化而出现滚动（非触摸导致滚）和触摸滚动时都会回调本方法**/
	@Override
	public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
		mFirstItemIndex = firstVisibleItem;	//headerView为0
		ensureFooterViewState();
	}

	@Override
	public void onScrollStateChanged(AbsListView view, int scrollState) {
		mScrollState = scrollState;
		ifNeedLoad(false);
	}

	private void ifNeedLoad(boolean fromClick) {
		if (mRefreshable && (fromClick || mFooterHasMore) && mScrollState == OnScrollListener.SCROLL_STATE_IDLE && !mLoading && mFooterShown) {
			mState = STATE_LOADING;
			if (fromClick) {
				setFooterHasMore(true);
				ensureFooterViewState();
			}
			onFooterLoading();
			postOnLoad();
			mLoading = true;
		}
	}

	private void setOnFooterClick() {
		mFooterView.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				ifNeedLoad(true);
			}
		});
	}

	private boolean isHeaderViewShown() {
		return getFirstVisiblePosition() == 0 && mHeaderView.getPaddingTop() > mHeaderHidePaddingTop;
		/*try {
			return getFirstVisiblePosition() == view.getPositionForView(mHeaderView);
		} catch (NullPointerException e) {}*/
	}

	private boolean isFooterViewShown() {
		int last = getLastVisiblePosition();
		return last >=0 && last == getCount() - 1;
		/*try {
			return getLastVisiblePosition() == view.getPositionForView(mFooterView);
		} catch (NullPointerException e) {}*/
	}

	private void decideIfStartRecoredAndUpdateMotionY(boolean pointerChanged, float motionY) {
		if (mRecored) {
			if (pointerChanged) mStartY = motionY - mPrevMotionY + mStartY;	//motionY - (mPrevMotionY - mStartY);
		} else if (mFirstItemIndex == 0) {	//说明下拉（这里是点击）到头了，可以开始拖动显示headerView了
			mRecored = true;
			mStartY = motionY;
			int startPaddingTop = mHeaderView.getPaddingTop();	//后面的计算过程中去掉了startPaddingTop的概念，解决了一些复杂状态的处理，也使计算变得简单
			if (startPaddingTop > mHeaderPullEnoughPaddingTop) {
				mStartY = motionY - ((startPaddingTop - mHeaderPullEnoughPaddingTop) * 1.0f * RATIO2 + mHeaderPullEnoughPaddingTop) * RATIO3;
			} else {
				mStartY = motionY - startPaddingTop * 1.0f * RATIO3;
			}
		}
		mPrevMotionY = motionY;
	}

	private float getPointerMotionY(MotionEvent e) {
		int motionY;
		if (mPointerId != -1 && e.getPointerCount() > 1) {
			/* 有个特别蛋疼的bug，虽然event.getPointerId(pointerIndex)返回1，但是
			 * 如果省略getPointerId(pointerIndex)方法，而直接给event.getY(pointerId)方法传1却不行。
			 */
			motionY = (int) e.getY(mPointerId);
		} else {	//当pointerCount为1时，获取pointerId会不确定，导致event.getY(pointerId)异常
			motionY = (int) e.getY();
		}
		return motionY;
	}

	@Override
	public boolean dispatchTouchEvent(MotionEvent e) {
		if (mRefreshable) {
			/* 主要判断在ACTION_MOVE事件时，按下或离开的其他手指（这里的事件触发时，不会同时触发下面的ACTION_MOVE事件，只会在下一次移动时触发）。
			 * 注意ACTION_DOWN是第一个手指按下时触发，ACTION_UP是最后一个手指离开时触发
			 */
			switch (e.getActionMasked()) {
			case MotionEvent.ACTION_POINTER_DOWN:
				mPointerId = e.getPointerId(e.getActionIndex());
				decideIfStartRecoredAndUpdateMotionY(true, e.getY(mPointerId));
				break;
			case MotionEvent.ACTION_POINTER_UP:
				if (e.getPointerId(e.getActionIndex()) == mPointerId) {
					mPointerId = -1;
				}
				mFingerUpped = true;
				break;
			}

			if (e.getAction() == MotionEvent.ACTION_DOWN) {
				mTouched = true;
				stopHeaderAnim();
				decideIfStartRecoredAndUpdateMotionY(false, e.getY());
			}
			boolean b = super.dispatchTouchEvent(e);

			switch (e.getAction()) {
			case MotionEvent.ACTION_UP:
			case MotionEvent.ACTION_CANCEL:
				if (mWaitingForDone) {
					mTouched = false;
					updateHeaderViewState(STATE_DONE);
					mWaitingForDone = false;
				} else {
					ensureIfHeaderHide();
					ensureIfHeaderBack();
				}
				mPointerId = -1;
				mRecored = false;
				mFingerUpped = false;
				break;
			}
			return b;
		} else {
			return super.dispatchTouchEvent(e);
		}
	}

	@Override
	public boolean onTouchEvent(MotionEvent e) {
		if (mRefreshable) {
			switch (e.getAction()) {
			case MotionEvent.ACTION_UP:
				mRecored = false;	//放在前边
				mTouched = false;
				if (mState != STATE_REFRESHING) {
					if (mState == STATE_PULL_TO_REFRESH) {	//还没下拉到可以刷新的时候，那么放弃刷新
						updateHeaderViewState(STATE_DONE);
					} else if (mState == STATE_RELEASE_REFRESH) {
						performRefreshing();
					}
				} else if (mWaitingForDone) {
					updateHeaderViewState(STATE_DONE);
					mWaitingForDone = false;
				} else {	//滚动到paddingTop=0位置
					startHeaderBackAnim();
				}
				mEventBlocked = false;
				break;
			case MotionEvent.ACTION_CANCEL:
				mRecored = false;	//放在前边
				mTouched = false;
				if (mState != STATE_REFRESHING) {
					updateHeaderViewState(STATE_DONE);
				} else if (mWaitingForDone) {
					updateHeaderViewState(STATE_DONE);
					mWaitingForDone = false;
				} else {	//滚动到paddingTop=0位置
					startHeaderBackAnim();
				}
				break;
			case MotionEvent.ACTION_MOVE:
				float motionY = getPointerMotionY(e);

				boolean motionYUpdated = false;
				if (mFingerUpped) {
					decideIfStartRecoredAndUpdateMotionY(true, motionY);	//换回原来的指头
					mFingerUpped = false;
					motionYUpdated = true;
				} else if (!mRecored) {
					decideIfStartRecoredAndUpdateMotionY(false, motionY);
					motionYUpdated = true;
				}

				if (mRecored) {
					int prevPaddingTop = mCurrentPaddingTop;
					mCurrentPaddingTop = (int)((motionY - mStartY) / RATIO3);

					if (mCurrentPaddingTop > mHeaderPullEnoughPaddingTop) {
						mCurrentPaddingTop = (mCurrentPaddingTop - mHeaderPullEnoughPaddingTop) / RATIO2 + mHeaderPullEnoughPaddingTop;
					} else {
						if (!motionYUpdated) {
							if (mState == STATE_REFRESHING) {
								mCurrentPaddingTop = mHeaderPullEnoughPaddingTop;
								decideIfStartRecoredAndUpdateMotionY(true, motionY);
								motionYUpdated = true;
							} else if (mCurrentPaddingTop < mHeaderHidePaddingTop) {
								mCurrentPaddingTop = mHeaderHidePaddingTop;
								decideIfStartRecoredAndUpdateMotionY(true, motionY);
								motionYUpdated = true;
							}
						}
					}

					if (mCurrentPaddingTop > prevPaddingTop) {	//向下拖拽
						if (getScrollY() <= 0) {	//滚到头了再下拉
							doPullHeaderView();
						}
					}
					//注意等于必须有，由于前面做了很多除法运算并取整，会造成原始不同的数据变得相同
					else if (mCurrentPaddingTop <= prevPaddingTop && isHeaderViewShown()) {
						if (mCurrentPaddingTop != prevPaddingTop) doPullHeaderView();
						if (mCurrentPaddingTop > mHeaderPullEnoughPaddingTop) {
							if (!mEventBlocked) {
								//如果阻止，则必须CANCEL，后续事件不可以再有选择的发送，否则ListView会滚动较大距离或判定为较大速度，导致混乱
								e.setAction(MotionEvent.ACTION_CANCEL);
								super.onTouchEvent(e);
								//换回来的目的是因为在重写的dispatchTouchEvent里面还要正常使用
								e.setAction(MotionEvent.ACTION_MOVE);
								mEventBlocked = true;
							}
						}
					}
				}
				if (!motionYUpdated) decideIfStartRecoredAndUpdateMotionY(false, motionY);
				break;
			}
		}
		return mEventBlocked ? true : super.onTouchEvent(e);
	}

	private void doPullHeaderView() {
		if (mState == STATE_REFRESHING) {
			if (mCurrentPaddingTop <= mHeaderPullEnoughPaddingTop) {
				if (mHeaderView.getPaddingTop() != mHeaderPullEnoughPaddingTop) {
					mHeaderView.setPadding(0, mHeaderPullEnoughPaddingTop, 0, 0);
				}
			} else {
				mHeaderView.setPadding(0, mCurrentPaddingTop, 0, 0);
				setSelection(0);
			}
		} else {
			updateHeaderViewState(mCurrentPaddingTop < mHeaderPullEnoughPaddingTop ? STATE_PULL_TO_REFRESH : STATE_RELEASE_REFRESH);
			mHeaderView.setPadding(0, mCurrentPaddingTop, 0, 0);
		}
	}

	private void updateHeaderViewState(int state) {
		if (state != mState) {
			if (mState == STATE_DONE) stopHeaderAnim();
			if (state == STATE_DONE) {
				//防止setRefreshComplete()在拖动中途被调用
				if (mTouched) {
					mWaitingForDone = true;
					return;
				}
			}
			int target = state;
			if (state == STATE_REFRESHING && mState != STATE_RELEASE_REFRESH) {
				state = STATE_RELEASE_REFRESH;
			}
			if (state == STATE_RELEASE_REFRESH && mState != STATE_PULL_TO_REFRESH) {
				mState = STATE_PULL_TO_REFRESH;
				ensureHeaderViewState();
				if (target == STATE_REFRESHING) {
					mState = STATE_RELEASE_REFRESH;
					ensureHeaderViewState();
				}
			}
			mState = target;
			ensureHeaderViewState();
		}
	}

	private void ensureHeaderViewState() {
		switch (mState) {
		case STATE_PULL_TO_REFRESH:
			onPull2Refresh();
			break;
		case STATE_RELEASE_REFRESH:
			onEnough2Release();
			break;
		case STATE_REFRESHING:
			startHeaderBackAnim();	//滚动到paddingTop=0位置
			mRefreshingTimeStart = System.currentTimeMillis();
			onRefreshing();
			break;
		case STATE_DONE:
			startHeaderHideAnim();
			break;
		}
	}

	private void ensureFooterViewState() {
		if (!mAttachedToWindow) return;
		if (isHeaderViewShown()) {
			if (mFooterView.getVisibility() == VISIBLE) {
				mFooterView.setVisibility(GONE);
				mFooterShown = false;
				onFooterHidden();
			}
			return;
		}
		if (mFooterView.getVisibility() != VISIBLE) mFooterView.setVisibility(VISIBLE);
		boolean shown = mFooterShown;
		mFooterShown = isFooterViewShown();
		final boolean shownChange = mFooterShown ^ shown;
		final boolean hasMoreChange = mFooterHasMorePrev ^ mFooterHasMore;
		if (shownChange || hasMoreChange) {
			if (mFooterShown) {
				onFooterShown(mFooterHasMore);
				if (hasMoreChange) {
					post(new Runnable() {	//不post不起作用
						@Override
						public void run() {
							//if (!shownChange) {
							//由于状态的改变导致mFooterView的高度可能不一致，若本ListView非满屏而不能滚动，则会导致mFooterView显示不全
							requestLayout();
							invalidate();
							//}
							smoothScrollToPosition(getCount() - 1);
						}
					});
				}
			} else {
				onFooterHidden();
			}
			if (hasMoreChange) mFooterHasMorePrev = mFooterHasMore;
		}
	}

	private void startHeaderHideAnim() {
		if (System.currentTimeMillis() - mRefreshingTimeStart >= mHeaderMinShowTime) {
			mHeaderHideAnimRun.run();
		} else {
			postDelayed(mHeaderHideAnimRun, mRefreshingTimeStart + mHeaderMinShowTime - System.currentTimeMillis());	//delayTime可以小于0
		}
	}

	private void hideHeaderDirectly() {
		if (!mScroller.isFinished()) {
			stopHeaderAnim();
			doHeaderHidden();
		} else if (mHeaderView.getPaddingTop() != mHeaderHidePaddingTop) {
			doHeaderHidden();
		}
	}

	private void ensureIfHeaderHide() {
		if (mState == STATE_DONE && mCurrentPaddingTop != mHeaderHidePaddingTop && mScroller.isFinished()) {
			mHeaderHideAnimRun.run();
		}
	}

	private void ensureIfHeaderHideWithDelay() {
		if (mState == STATE_DONE && mCurrentPaddingTop != mHeaderHidePaddingTop && mScroller.isFinished()) {
			startHeaderHideAnim();
		}
	}

	private void ensureIfHeaderBack() {
		if (mState == STATE_REFRESHING && mCurrentPaddingTop != mHeaderPullEnoughPaddingTop && mScroller.isFinished()) {
			mHeaderBackAnimRun.run();
		}
	}

	private void startHeaderBackAnim() {
		mHeaderBackAnimRun.run();
	}

	private void stopHeaderAnim() {
		if (!mScroller.isFinished()) mScroller.abortAnimation();
		removeCallbacks(mHeaderHideAnimRun);
		removeCallbacks(mHeaderBackAnimRun);
	}

	private final Runnable mHeaderHideAnimRun = new Runnable() {
		@Override
		public void run() {
			if (!mScroller.isFinished() && mScroller.getFinalY() == mHeaderHidePaddingTop) {
				//等其完成，即隐藏了header，不重新开始动画
			} else {
				if (!startScroller(mHeaderHidePaddingTop - mCurrentPaddingTop)) {
					doHeaderHidden();
				}
			}
		}
	};

	private final Runnable mHeaderBackAnimRun = new Runnable() {
		@Override
		public void run() {
			if (!mScroller.isFinished() && mScroller.getFinalY() == mHeaderPullEnoughPaddingTop) {
				//等其完成，即隐藏了header，不重新开始动画
			} else {
				startScroller(mHeaderPullEnoughPaddingTop - mCurrentPaddingTop);
			}
		}
	};

	private boolean startScroller(int delta) {
		stopHeaderAnim();
		if (delta != 0) {
			mScroller.startScroll(0, mCurrentPaddingTop, 0, delta, mHeaderHideAnimDuration);
			invalidate();
			return true;
		} else {
			return false;
		}
	}

	@Override
	public void computeScroll() {
		super.computeScroll();
		if (mScroller.computeScrollOffset()) {
			mCurrentPaddingTop = mScroller.getCurrY();
			if (mScroller.isFinished()) {
				if (mCurrentPaddingTop == mHeaderHidePaddingTop) {
					doHeaderHidden();
				} else {
					ensureIfHeaderHideWithDelay();
				}
			} else {
				mHeaderView.setPadding(0, mCurrentPaddingTop, 0, 0);
				invalidate();
			}
		}
	}

	private void doHeaderHidden() {
		mHeaderView.setPadding(0, mHeaderHidePaddingTop, 0, 0);
		//不能setVisibility(View.GONE)，会导致header实际高度改变
		onHeaderHidden();
		if (mCurrentPaddingTop != mHeaderHidePaddingTop) mCurrentPaddingTop = mHeaderHidePaddingTop;
	}

	protected AnimationDrawable ensureFrameAnim(ImageView imgView, int animDrawableId) {
		AnimationDrawable frameAnim = (AnimationDrawable)imgView.getDrawable();
		if (frameAnim == null) {
			frameAnim = (AnimationDrawable)getResources().getDrawable(animDrawableId);
			imgView.setImageDrawable(frameAnim);
		}
		return frameAnim;
	}

	protected void postOnRefresh() {
		if (mRefreshListener != null) mRefreshListener.onRefresh();
	}

	protected void postOnLoad() {
		if (mRefreshListener != null) mRefreshListener.onLoad();
	}

	private void setFooterHasMore(boolean hasMore) {
		//不应该在这赋值，而应该在ensureFooterViewState()之后
		//mFooterHasMorePrev = mFooterHasMore;
		mFooterHasMore = hasMore;
		//可能数据没有变导致onScroll(xx, xx, xx)没有执行，但是状态确实改变了
		ensureFooterViewState();
	}

	public void setRefreshComplete(final boolean hasMore) {
		if (mAttachedToWindow) {
			post(new Runnable() {
				@Override
				public void run() {
					updateHeaderViewState(STATE_DONE);
					setFooterHasMore(hasMore);
				}
			});
			mSuspendSetRefreshComplete = false;
		} else {
			mSuspendHasMore = hasMore;
			mSuspendSetRefreshComplete = true;
		}
	}

	public void setLoadComplete(final boolean hasMore) {
		if (mAttachedToWindow) {
			post(new Runnable() {
				@Override
				public void run() {
					setFooterHasMore(hasMore);
					if (mState == STATE_LOADING) updateHeaderViewState(STATE_DONE);
					mLoading = false;
				}
			});
			mSuspendSetLoadComplete = false;
		} else {
			mSuspendHasMore = hasMore;
			mSuspendSetLoadComplete = true;
		}
	}

	public void performRefreshing() {
		if (mAttachedToWindow) {
			if (getAdapter() == null) setAdapter(EMPTY_ADAPTER);
			updateHeaderViewState(STATE_REFRESHING);
			postOnRefresh();
			mSuspendPerformRefreshing = false;
		} else {
			mSuspendPerformRefreshing = true;
		}
	}

	@Override
	protected void onAttachedToWindow() {
		super.onAttachedToWindow();
		mAttachedToWindow = true;
		if (mSuspendPerformRefreshing) performRefreshing();
		if (mSuspendSetRefreshComplete) setRefreshComplete(mSuspendHasMore);
		if (mSuspendSetLoadComplete) setLoadComplete(mSuspendHasMore);
	}

	@Override
	protected void onDetachedFromWindow() {
		mAttachedToWindow = false;
		super.onDetachedFromWindow();
	}

	protected abstract View getLoadingViewHeader(LayoutInflater inflater);
	protected abstract View getLoadingViewFooter(LayoutInflater inflater);

	/**拖拽出了足够的位置，可以释放进行刷新了**/
	protected abstract void onEnough2Release();
	/**正在向外拖拽，但位置还达不到可以释放以刷新的程度**/
	protected abstract void onPull2Refresh();
	protected abstract void onRefreshing();
	protected abstract void onHeaderHidden();

	protected abstract void onFooterShown(boolean hasMore);
	protected abstract void onFooterLoading();
	protected abstract void onFooterHidden();

	public void setOnRefreshListener(OnRefreshListener l) {
		mRefreshListener = l;
		mRefreshable = true;
	}

	public interface OnRefreshListener {
		void onRefresh();
		void onLoad();
	}

	private static final ListAdapter EMPTY_ADAPTER = new BaseAdapter() {
		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			return null;
		}
		@Override
		public long getItemId(int position) {
			return 0;
		}
		@Override
		public Object getItem(int position) {
			return null;
		}
		@Override
		public int getCount() {
			return 0;
		}
	};
}
